package com.pactera.madp.cp.aop;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.pactera.madp.cp.common.constant.Constants;
import com.pactera.madp.cp.context.SyncStateContext;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.Date;
import java.util.concurrent.TimeUnit;

@Slf4j
@Aspect
@Configuration
@AllArgsConstructor
public class SyncAspect {

    private final RedisTemplate redisTemplate;

    @Pointcut("execution(* com.pactera.madp.cp.service.sync.template.SyncItemService.handler())")
    public void syncPointcCut() {}

    @Around("syncPointcCut()")
    public void around(ProceedingJoinPoint point) throws Throwable {
        log.debug(SyncStateContext.get().getSyncSubType() + "AOP执行...");
        String syncDate = DateUtil.format(new Date(), Constants.DATE_FORMAT);
        SyncStateContext.get().setSyncDate(syncDate);

        String className = point.getTarget().getClass().getSimpleName();
        String lock = StrUtil.format("{}{}",Constants.SYNC_LOCK_PREFIX, className.substring(4,className.length() - 11));
        Boolean isLocked;
        try {
            // 获取锁
            isLocked = redisTemplate.boundValueOps(lock).setIfAbsent(1, Constants.EXPIRE_TIME, TimeUnit.SECONDS);
            if (!isLocked) {
                SyncStateContext.get().setSaveLog(false);
                SyncStateContext.get().setExeBusiness(false);
                return;
            }
            log.debug(SyncStateContext.get().getSyncSubType() + "获取锁成功");

            // 查询任务状态
            String taskState = StrUtil.format("{}{}", Constants.SYNC_STATE_PREFIX, className.substring(4, className.length() - 11));
            boolean flag = StrUtil.equals((String) redisTemplate.boundValueOps(taskState).get(), syncDate);
            if (flag) {
                // 已执行过
                SyncStateContext.get().setSaveLog(false);
                return;
            }
            log.debug(SyncStateContext.get().getSyncSubType() + "执行任务");
            // 执行任务
            point.proceed();
            // 保存执行成功状态
            if (SyncStateContext.get().isFinalState()) {
                log.debug(SyncStateContext.get().getSyncSubType() + "保存执行状态");
                redisTemplate.boundValueOps(taskState).set(syncDate);
            }
        } finally {
            // 释放锁
            redisTemplate.delete(lock);
            log.debug(SyncStateContext.get().getSyncSubType() + "释放锁");
        }
    }
}
